package com.zzl.alligator.framework.security.filter;

import com.zzl.alligator.common.util.JsonUtils;
import com.zzl.alligator.framework.cache.ICache;
import com.zzl.alligator.framework.cache.support.CacheSpecEnum;
import com.zzl.alligator.framework.exception.VerifyCodeException;
import com.zzl.alligator.framework.security.hanlder.LoginFailureHandler;
import com.zzl.alligator.framework.support.web.vo.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * TODO
 *
 * @author zhouziliang
 * @since 2020/6/28
 */
@Component
@Slf4j
public class VerifyCodeFilter extends OncePerRequestFilter {

    @Autowired
    private LoginFailureHandler loginFailureHandler;

    @Autowired
    private ICache cache;

    /**
     * Same contract as for {@code doFilter}, but guaranteed to be
     * just invoked once per request within a single request thread.
     * See {@link #shouldNotFilterAsyncDispatch()} for details.
     * <p>Provides HttpServletRequest and HttpServletResponse arguments instead of the
     * default ServletRequest and ServletResponse ones.
     *
     * @param request
     * @param response
     * @param filterChain
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        if ("/login".equals(request.getServletPath()) && "post".equalsIgnoreCase(request.getMethod())) {
            try {
                validate(request);
            } catch (VerifyCodeException e) {
                response.setHeader("Content-type", "application/json;charset=UTF-8");
                PrintWriter writer = response.getWriter();
                writer.write(JsonUtils.toJsonString(JsonResult.error(402, e.getMessage())));
                writer.flush();
                writer.close();
                return;
            }
        }
        // 3. 校验通过，就放行
        filterChain.doFilter(request, response);
    }

    /**
     * 验证保存在session的验证码和表单提交的验证码是否一致
     */
    private void validate(HttpServletRequest request) throws ServletRequestBindingException {
        String captcha = ServletRequestUtils.getStringParameter(request, "code");
        String code = cache.getCacheObject(CacheSpecEnum.VARIFY_CODE, request.getParameter("uuid"));
        if (code == null || !code.equalsIgnoreCase(captcha)) {
            throw new VerifyCodeException("验证码不正确！");
        }
        request.getSession().removeAttribute(request.getParameter("uuid"));
    }
}
